import type { ReactFlowJsonObject, Node as ReactFlowNode } from 'reactflow'

// 支持的节点类型
export enum BlockEnum {
  Start = 'start',
  End = 'end',
  LLM = 'llm',
  KnowledgeRetrieval = 'qa_retriever',
  IfElse = 'if-else',
  Code = 'code',
  Tool = 'tool',
  Iteration = 'iteration',
  IterationStart = 'iteration_start',
  IterationEnd = 'iteration_end',
  Intend = 'intend',
  Workflow = 'workflow',
  Answer = 'answer',
  QuestionClassifier = 'question-classifier',
  TemplateTransform = 'template-transform',
  HttpRequest = 'http_request',
  VariableAssigner = 'variable-assigner',
  VariableAggregator = 'variable-aggregator',
  ParameterExtractor = 'parameter-extractor',
  Assigner = 'assigner',
  DocExtractor = 'doc_extractor',
  TextConcatenation = 'text_concatenation',
  VarUpdate = 'var_update',
  List = 'list',
  Loop = "loop",
  LoopStart = "loop_start",
  LoopEnd = "loop_end",
}

// 工作流基本信息
export type WorkflowType = {
  id?: string
  name: string
  category_code?: string
  description?: string
  logo?: string
  graph: ReactFlowJsonObject | null
  user_id?: string | number
  enterprise_id?: string
  // 创建和更新相关信息
  created_by?: string
  created_at?: string
  updated_by?: string
  updated_at?: string
  // 上线状态
  status: number
  // 环境变量
  environment_variables?: object
}

// 工作流运行状态
export enum WorkflowRunningStatus {
  Verifying = 'verifying',
  Invalid = 'invalid',
  Waiting = 'waiting',
  Running = 'running',
  Succeeded = 'succeeded',
  Failed = 'failed',
  Stopped = 'stopped'
}

// 节点运行状态
export enum NodeRunningStatus {
  Verifying = 'verifying',
  Invalid = 'invalid',
  NotStart = 'not-start',
  Waiting = 'waiting',
  Running = 'running',
  Succeeded = 'succeeded',
  Failed = 'failed'
}

export type Branch = {
  id: string
  name: string
}

export type ToolDefaultValue = {
  provider_id: string
  provider_type: string
  provider_name: string
  tool_name: string
  tool_label: string
  title: string
}

export type CommonNodeType<T = {}> = {
  _connectedSourceHandleIds?: string[]
  _connectedTargetHandleIds?: string[]
  _targetBranches?: Branch[]
  _isSingleRun?: boolean
  _runningStatus?: NodeRunningStatus
  _singleRunningStatus?: NodeRunningStatus
  _isCandidate?: boolean
  _isBundled?: boolean
  _children?: string[]
  _isEntering?: boolean
  _showAddVariablePopup?: boolean
  _holdAddVariablePopup?: boolean
  _iterationLength?: number
  _iterationIndex?: number
  isIterationStart?: boolean
  isInIteration?: boolean
  iteration_id?: string
  selected?: boolean
  title: string
  desc: string
  type: BlockEnum
  width?: number
  height?: number
  variables?: [] | null
  id: string
} & T &
  Partial<Pick<ToolDefaultValue, 'provider_id' | 'provider_type' | 'provider_name' | 'tool_name'>>

export type FlowNode<T = {}> = ReactFlowNode<CommonNodeType<T>>

export type SelectedNode = Pick<FlowNode, 'id' | 'data'>

export type NodeProps<T = unknown> = { id: string; data: CommonNodeType<T> }
export type NodePanelProps<T> = {
  id: string
  data: CommonNodeType<T>
}

export type GlobalVariable = {
  name: string
  value_type: 'string' | 'number'
  description: string
}

export type VariableWithValue = {
  key: string
  value: string
}

export type ValueSelector = string[] // [nodeId, key | obj key path]

export enum TransferMethod {
  all = 'all',
  local_file = 'local_file',
  remote_url = 'remote_url'
}

export enum SupportUploadFileTypes {
  image = 'image',
  document = 'document',
  audio = 'audio',
  video = 'video',
  custom = 'custom'
}
export type UploadFileSetting = {
  allowed_file_upload_methods: TransferMethod[]
  allowed_file_types: SupportUploadFileTypes[]
  allowed_file_extensions?: string[]
  max_length: number
  number_limits?: number
}

export enum VarKindType {
  variable = 'variable',
  constant = 'constant',
  mixed = 'mixed'
}

export type Variable = {
  variable: string
  label?:
    | string
    | {
        nodeType: BlockEnum
        nodeName: string
        variable: string
      }
  value_selector: ValueSelector
  variable_type?: VarKindType
  value?: string
  options?: string[]
  required?: boolean
  isParagraph?: boolean
}

export type ModelConfig = {
  provider: string
  name: string
  mode: string
  completion_params: Record<string, any>
}

export enum PromptRole {
  system = 'system',
  user = 'user',
  assistant = 'assistant'
}

export type NodeDefault<T> = {
  defaultValue: Partial<T>
  getAvailablePrevNodes: () => BlockEnum[]
  getAvailableNextNodes: () => BlockEnum[]
  checkValid: (payload: T, t: any, moreDataForCheckValid?: any) => { isValid: boolean; errorMessage?: string }
}
